﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Brain.IO;
using System.IO;

namespace Brain.Editor
{
    public partial class MakeTerrainForm : Form
    {
        private Random random;

        private DefaultContentManager content;
        public MakeTerrainForm()
        {
            random = new Random();
            InitializeComponent();

            //HeightMap

            this.terrainControl1.OnDraw += new SetVoid(terrainControl1_OnDraw);

            content = new DefaultContentManager();
        }



        #region Default Options
        private bool defaultOptionChanged = false;
        private void numeric_DistanceHeights_ValueChanged(object sender, EventArgs e)
        {
            defaultOptionChanged = true;
        }
        #endregion

        void terrainControl1_OnDraw()
        {
            if (radio_HeightMap.Checked)
            {
                if (heightMapOptionsModified && heightMapTex != null && !heightMapTex.IsDisposed || 
                    defaultOptionChanged && heightMapTex != null && !heightMapTex.IsDisposed)
                {
                    if (this.terrainControl1.Terrain != null)
                    {
                        this.terrainControl1.Terrain.Dispose();
                    }
                    this.terrainControl1.Terrain = new TerrainWorldObject(heightMapTex, (float)this.numeric_HeightFactor.Value);
                    this.terrainControl1.Terrain.HeightMap.OffsetBetweenHeights = (float)this.numeric_DistanceHeights.Value;

                    heightMapOptionsModified = false;
                    defaultOptionChanged = false;
                }
            }
            else if (radio_Procedural.Checked)
            {
                if (proceduralOptionsChanged || defaultOptionChanged)
                {
                    if (this.terrainControl1.Terrain != null)
                    {
                        this.terrainControl1.Terrain.Dispose();
                    }
                    this.terrainControl1.Terrain = new TerrainWorldObject();
                    this.terrainControl1.Terrain.HeightMap.OffsetBetweenHeights = (float)this.numeric_DistanceHeights.Value;

                    // Generate Heights
                    HeightMap map = this.terrainControl1.Terrain.HeightMap;
                    map.Width = (int)this.numeric_Width.Value;
                    map.Height = (int)this.numeric_Height.Value;
                    map.Heights = new float[map.Width, map.Height];

                    bool useNoise = this.checkBox_Noise.Checked;

                    if (useNoise)
                    {
                        random = new Random((int)this.numeric_NoiseSeed.Value);

                        float strength = (float)this.numeric_NoiseStrength.Value;
                        for (int x = 0; x < map.Width; x++)
                        {
                            for (int z = 0; z < map.Height; z++)
                            {
                                map.Heights[x, z] = (random.Next(10, 100) / 100f) * strength;
                            }
                        }
                    }

                    Engine.Instance.RenderManager3D.InitializeTerrainDefaultRendering(this.terrainControl1.Terrain, true, false);
                    proceduralOptionsChanged = false;
                    defaultOptionChanged = false;
                }
            }
        }

        #region Height Map

        bool heightMapOptionsModified = false;
        Texture2D heightMapTex;
        private void button_ImportHeightMap_Click(object sender, EventArgs e)
        {
            AssetManager manager = new AssetManager(true);
            if (manager.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                ContentProjectFile file = manager.SelectedFile;
                string s = "confile:" + file.Name;
                this.textBox_HeightMapName.Text = s;

                this.heightMapOptionsModified = true;

                if (heightMapTex != null)
                {
                    heightMapTex.Dispose();
                }
                heightMapTex = content.Load<Texture2D>(s);
                //Width: 100 Height: 100
                this.label_WidthHeight.Text = string.Format("Width: {0} Height: {1}", heightMapTex.Width, heightMapTex.Height);
            }
        }
        private void numeric_HeightFactor_ValueChanged(object sender, EventArgs e)
        {
            this.heightMapOptionsModified = true;
        }
        private void radio_HeightMap_CheckedChanged(object sender, EventArgs e)
        {
            this.heightMapOptionsModified = true;
        }
        #endregion

        #region Procedural
        private bool proceduralOptionsChanged = false;
        private void button_Randomize_Click(object sender, EventArgs e)
        {
            numeric_NoiseSeed.Value = random.Next();
            proceduralOptionsChanged = true;
        }
        private void proceduralValueChanged(object sender, EventArgs e)
        {
            proceduralOptionsChanged = true;
        }
        private void radio_Procedural_CheckedChanged(object sender, EventArgs e)
        {
            proceduralOptionsChanged = true;
        }
        #endregion

        private void button_ToAsset_Click(object sender, EventArgs e)
        {
            InputTextDialog dialog = new InputTextDialog("Terrain Naming", "Terrain Name");

            string fileName = "";
            ContentProjectFile file = new ContentProjectFile();
            if (this.terrainControl1.Terrain != null && dialog.ShowDialog() == DialogResult.OK)
            {
                file.Project = Engine.Instance.SerializationManager.LevelData.ContentProject;
                file.FileExtension = ".brterrain";
                file.Name = dialog.InputText;
                file.NeedsProcessing = false;
                file.SaveOnEditorSave = true;
                file.RelativePath = dialog.InputText;

                TerrainFile terrain = new TerrainFile();
                terrain.Heights = this.terrainControl1.Terrain.HeightMap.Heights;
                terrain.DistanceBetweenHeights = this.terrainControl1.Terrain.HeightMap.OffsetBetweenHeights;

                fileName = Path.Combine(Path.Combine(Engine.Instance.SerializationManager.LevelData.RootFolder, "Content"), dialog.InputText + ".brterrain");
                file.ProcessedPath = fileName;
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
                using (FileStream stream = new FileStream(fileName, FileMode.Create))
                {
                    terrain.Serialize(stream);
                }

                Engine.Instance.SerializationManager.LevelData.ContentProject.Files.Add(file);
            }

            TerrainWorldObject ter = new TerrainWorldObject(fileName, false, true);
            ter.Rendering = WorldObjectRendering.Rendered;
            GameScreen gs = Engine.Instance.ScreenManager.GetScreen(0);
            gs.AddComponent(ter);

            file.LoadedData = ter.HeightMap;
            
            this.Close();
        }
    }
}
